package com.pool.activity;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;

import com.pool.R;
import com.pool.activity.common.FullscreenActivity;
import com.pool.auth.Auth;
import com.pool.common.Strings;
import com.pool.net.Internet;

/**
 * This {@link Activity} is a gate to an other activity requiring the user to be logged in.
 * It checks if a authentication token is stored, and then runs the passed {@link Intent}. If no
 * token is in stored, it opens a {@link Dialog} asking for crendentials and then connects to the
 * service. If the authentication is successful, it runs the passed {@link Intent}, otherwise
 * displays a {@link Dialog} with an error message and finishes, without running the {@link Intent}. 
 * 
 * @author claveld@gmail.com (David Clavel)
 */
public class LoginAndRun extends FullscreenActivity {

  private static final String TAG = "LoginAndRun";
  
  private static final String INTENT_TO_RUN = "intentToRun";

  private static final int DIALOG_UNABLE_TO_LOAD = 0;
  private static final int DIALOG_LOGIN_AND_RUN = 1;
  private static final int DIALOG_FILL_EMAIL_PASSWORD = 2;
  private static final int DIALOG_CONNECTION = 3;
  private static final int DIALOG_INVALID_AUTH = 4;
  private static final int DIALOG_CHECK_INTERNET = 5;

  private static final int LOGIN_OK_AND_RUN_REQUEST_CODE = 0;
  
  private final LoginAndRunHandler handler;
  private final Auth auth;

  public LoginAndRun() {
    auth = Auth.get();
    handler = new LoginAndRunHandler(this);
  }
  
  public static Intent createFor(Context context, Class<?> clazz) {
    Intent intent = new Intent(context, LoginAndRun.class);
    intent.putExtra(INTENT_TO_RUN, clazz.getName());
    return intent;
  }
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    String intentClassName = getIntent().getExtras().getString(INTENT_TO_RUN);

    // Check that the current extra data is valid.
    Class<?> clazz = getClass(intentClassName);
    if (clazz == null) {
      showDialog(DIALOG_UNABLE_TO_LOAD);
    }
    
    if (Auth.get().isAlreadyLogged()) {
      startActivityForResult(new Intent(this, clazz), LOGIN_OK_AND_RUN_REQUEST_CODE);
      return;
    }
    
    showDialog(DIALOG_LOGIN_AND_RUN);
  }

  private Class<?> getClass(String intentClassName) {
    try {
      return Class.forName(intentClassName);
    } catch (ClassNotFoundException e) {
      return null;
    }
  }
  
  @Override
  protected Dialog onCreateDialog(int id) {
    String className = getIntent().getExtras().getString(INTENT_TO_RUN);
    switch(id) {
      case DIALOG_UNABLE_TO_LOAD:
        return new AlertDialog.Builder(this)
            .setTitle("Unable to load")
            .setMessage("Unable to load class " + className)
            .setPositiveButton(R.string.ok, null)
            .create();
      case DIALOG_LOGIN_AND_RUN:
        Class<?> clazz = getClass(className);
        Intent intentToRun = new Intent(this, clazz);
        return createLoginDialog(intentToRun);
      case DIALOG_FILL_EMAIL_PASSWORD:
        return createAlertDialog(R.string.authentication_failed,
                                 R.string.fill_email_and_password);
      case DIALOG_CONNECTION:
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage(Strings.getString(R.string.connecting));
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        return dialog;
      case DIALOG_INVALID_AUTH:
        return createAlertDialog(R.string.authentication_failed, R.string.check_credentials);
      case DIALOG_CHECK_INTERNET:
        return createAlertDialog(R.string.authentication_failed, R.string.check_internet);
      default:
        Log.i(TAG, "Unknown dialog id: " + id);
    }
    return null;
  }
  
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    finish();
  }
  
  private Dialog createLoginDialog(final Intent intentToRun) {
    LayoutInflater factory = LayoutInflater.from(this);
    final View textEntryView = factory.inflate(R.layout.alert_dialog_text_entry, null);
    return new AlertDialog.Builder(this)
      //.setIcon(android.R.drawable.alert_dialog_icon)
      .setTitle(R.string.login)
      .setView(textEntryView)
      .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          new Thread() {
            public void run() {
              EditText userEditText = (EditText) textEntryView.findViewById(R.id.username_edit);
              EditText passwordEditText = (EditText) textEntryView.findViewById(R.id.password_edit);
              String username = userEditText.getText().toString();
              String password = passwordEditText.getText().toString();

              tryLogin(username, password, intentToRun);
            }
          }.start();
        }
      })
      .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
          finish();
        }
      })
      .create();
  }
  
  private Dialog createAlertDialog(int titleId, int messageId) {
    return new AlertDialog.Builder(this)
      .setTitle(titleId)
      .setMessage(messageId)
      .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
          finish();
        }
      })
      .create();
  }
  
  private void tryLogin(String email, String password, Intent intent) {
    if (Strings.anyEmpty(email, password)) {
      handler.showDialog(DIALOG_FILL_EMAIL_PASSWORD);
      return;
    }

    handler.showDialog(DIALOG_CONNECTION);
    String authKey = auth.authenticate(email, password);
    removeDialog(DIALOG_CONNECTION);

    if (authKey == null) {
      if (!Internet.isWifiEnabled()) {
        handler.showDialog(DIALOG_CHECK_INTERNET);
      } else {
        handler.showDialog(DIALOG_INVALID_AUTH);
      }
      return;
    }

    startActivityForResult(intent, LOGIN_OK_AND_RUN_REQUEST_CODE);
  }
}
